package com.ericsson.entironment.interfaces.receiver;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.ericsson.common.date.AppliedDate;
import com.ericsson.common.util.ByteUtil;
import com.ericsson.entironment.interfaces.adapter.WMMPAdapter;
import com.ericsson.entironment.interfaces.message.CommonMessage;
import com.ericsson.entironment.manager.TermManager;
import com.ericsson.entironment.util.SysParams;

public class WMMPMessageReceiver extends MessageReceiver
{
	private static Log log=LogFactory.getLog(WMMPMessageReceiver.class);
	private CommonMessage message=null;
	public void run()
	{
		DatagramSocket conn=null;
		byte[] buff=new byte[1024];
		byte[] temp;
		int i;
		WMMPAdapter adapter=new WMMPAdapter();
		try
		{
			conn=new DatagramSocket(SysParams.getInstance().getPorts(this.protocol));
			//InetAddress add=InetAddress.getByName("192.168.1.18"); //("222.128.29.224");
			DatagramPacket msg=new DatagramPacket(buff,buff.length); 
			while(true)
			{
				conn.receive(msg);
				temp=new byte[msg.getLength()];
				for(i=0;i<temp.length;i++)
				{
					temp[i]=msg.getData()[i];
				}
				
				if (log.isDebugEnabled())
					log.debug("\n "+AppliedDate.getInstance().getDateTimeWithSep()+" Message received from"+msg.getAddress().getHostAddress()+" \n"+ByteUtil.byte2String(temp)+"\n");
				//调用WMMP方式解析器
				message=new CommonMessage();
				dispose(msg,temp,conn);
				//返回
			}
			
		}
		
		catch (SocketException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		catch (UnknownHostException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		catch (IOException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally
		{
			conn.close();
		}
		
	}
	public  void dispose(DatagramPacket msg,byte[] request,DatagramSocket conn) 
	{
		
		InetAddress add=msg.getAddress();
		String result=null;
		String body;
		int i;
		int port=msg.getPort();
		byte[] header={0x00,0x00,(byte)0x80,0x04,0x00,0x00,0x00,0x01,0x02,0x00,0x00,0x00,
					   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
		};
				
		//首先检查消息长度是否大于消息头
		if (request.length<28)
		{
			result="\r\n\r\n\r\n消息长度错误，无法解析\r\n";
			//发送响应
			sendResponse(result,header,add,conn,port);
			//返回
			return;
		}
		//检查报文总长度是否合法
		
		if (byte2Int(request,0,2)!=request.length)
		{
			result="\r\n\r\n\r\n消息长度与消息头中指明的长度不符\r\n";
			//发送响应
			sendResponse(result,header,add,conn,port);
			//返回
			return;
		}
		
		//检查消息类型代码
		
		if (byte2Int(request,2,2)!=4)
		{
			result="\r\n\r\n\r\n消息类型不正确\r\n";
			//发送响应
			sendResponse(result,header,add,conn,port);
			//返回
			return;
		}
		
		//检查版本号
		if (request[8]!=2)
		{
			result="\r\n\r\n\r\n消息版本号不正确，只能接受2.0的消息\r\n";
			//发送响应
			sendResponse(result,header,add,conn,port);
			//返回
			return;
		}
		
		//取出消息体
		body=new String(request,28,request.length-28);
		try
		{
			result=disposeBody(body);
		}
		catch(Exception e)
		{
			e.printStackTrace();
			result="\r\n\r\n\r\n消息体解析失败，无法识别业务内容\r\n";
			//发送响应
			sendResponse(result,header,add,conn,port);
			//返回
			return;
		}
		//发送消息
		for(i=0;i<28;i++)
		{
			header[i]=request[i];
		}
		
		sendResponse(result,header,add,conn,port);
	

		
	}
	
	public  void sendResponse(String result,byte[] header,InetAddress add,DatagramSocket conn,int port)
	{
		try
		{
			byte[] response=null;
			int length;
			int i;
			byte[] body=result.getBytes();
			//计算消息总长度
			length=28+body.length;
			
			//将消息总长度放入header
			header[0]=(byte) ((0xFF00&length)>>8);
			header[1]=(byte) (0xFF&length);
			
			//将响应代码放入header
			header[2]=(byte) 0x80;
			header[3]=0x04;
			
			//合并消息同消息体
			response=new byte[length];
			
			for(i=0;i<28;i++)
			{
				response[i]=header[i];
			}
			for(i=28;i<length;i++)
			{
				response[i]=body[i-28];
			}
			
			DatagramPacket msg=new DatagramPacket(response,response.length,add,port); 
			conn.send(msg);
			if (log.isDebugEnabled())
				log.debug("\n "+AppliedDate.getInstance().getDateTimeWithSep()+"Message Sended to "+add.getHostAddress()+":"+port+"\n"+result+"\n"+byte2String(response)+"\n");
		
		}
		catch (SocketException e)
		{
			log.error(e);
		}
		catch (UnknownHostException e)
		{
			// TODO Auto-generated catch block
			log.error(e);
		}
		catch (IOException e)
		{
			// TODO Auto-generated catch block
			log.error(e);
		}
	}
	private  String disposeBody(String body) throws UnsupportedEncodingException
	{
		int i=0;
		int j;
		int n1=0;
		int n2;
		int start;
		String result="";
		String value;
		String temp;
		String dital="";
		String dot;
		int dotpos;
		String sequence="";
		String code="";
		String flag="83";
		
		body=body.toUpperCase();
		//查找第3个0D0A
		start=-2;
		while((start=body.indexOf("\r\n",start+2))!=-1)
		{
			if (i==0)
			{//帧编号
				sequence=body.substring(0,start);
			}
			if (i==1)
			{//终端序列号
				code=body.substring(n1,start);
				//检查序列号是否已注册
				if (!TermManager.isSequenceExist(code))
				{//序列号不合法
					return sequence+"\r\n"+code+"\r\n"+flag+"\r\n该终端未在系统中注册\r\n";
				}
				
				this.message.setTerminalseq(code);
			}
			if (i==2)
			{
				dital=body.substring(n1,start);
			}
			i++;
			if (i==3)
				break;
			n1=start+2;//记录第二个ODOA的位置
		}
		
		if (i<3)
		{//没有发现第三个0D0A, 数据段格式不全
			
			return sequence+"\r\n"+code+"\r\n"+flag+"\r\n业务数据格式不正确，未能找到数据内容段\r\n";
		}
		if (!dital.equals("03"))
		{//没有发现第三个0D0A, 数据段格式不全
			
			return sequence+"\r\n"+code+"\r\n"+flag+"\r\n业务消息类型不正确，帧类别应为03\r\n";
		}
		
		
		//从第二个0D0A开始查找第三个OAOD，开始处理数据段内容
		i=1;
		String frameValue="";
		while((n2=body.indexOf("\r\n",n1))!=-1)
		{	
			if (n2+2==body.length())
				break;//已达消息结尾
			value="";
			//判断该数据是否为负值
			if (body.substring(n2+2,n2+3).equals("-"))
			{//该通道业务数据是负值
				value+="-";
				
			  //取出剩余几位的值
			   temp=body.substring(n2+3,n2+6);
				  	
			   temp=""+Integer.parseInt(temp,16);//按照16进制转换为整形
				
			}
			else
			{//不是负值，将该位转换为数值
				  //取出剩余几位的值
				  temp="";

				  temp=body.substring(n2+2,n2+6);
			      temp=""+Integer.parseInt(temp,16);//按照16进制转换为整形
			}
			//检查是否存在小数
			
			dot=body.substring(n2+7,n2+8);
			 
			 dotpos=Integer.parseInt(dot,16);//按照16进制转换为整形
			 
			 if (dotpos!=0)
			 {//存在小数点
				 value+=temp.substring(0,dotpos)+"."+temp.substring(dotpos,temp.length());
			 }
			 else
			 {
				 value+=temp;
			 }
			 
			
			n1=n2+2;
			this.message.addValues(value);
			frameValue+="信道:"+i+" 传输值为:"+value+";";
			i++;
		}
		
		result=sequence+"\r\n"+code+"\r\n"+flag+"\r\n"+"OK\r\n"+frameValue+"\r\n";
		this.message.save();
		return result;
		
	}
	
	private static String byte2String(byte[] in)
	{
		String out="";
		String tmp;
		int i;
		int a;
		for(i=0;i<in.length;i++)
		{
			a=in[i]&0xFF;
			tmp=Integer.toHexString(a);
			if (tmp.length()==1)
			{
				tmp="0"+tmp;
			}
			out+=tmp+" ";
		}
		return out;
	}
	
	private static int byte2Int(byte[] in,int start,int length)
	{
		int a=0;
		int i;

		for ( i =start; i<start+length ; i++) {   
  
			a=a<<8;
            a+= (in[i] & 0xFF);   
             
        }  
		return a;
	}

}
